#pragma once
#include <string>
#include <fstream>
#include <iostream>
#include <memory.h>
#include <map>
#include "Node.h"
#include "Link.h"
#include "Graph.h"
#include "YenTopKShortestPathsAlg.h"
using namespace std;
class NetStruture
{

public:

	typedef map<int,Node> NODES;
	typedef map<int,map<int,Link*>> LINKS;
	typedef map<int,map<int,double>> S_D_FLOWS;
	typedef map<int,map<int,vector<vector<int>>>> PATHS;
	// Constructors and Destructor
	NetStruture(const string &nodes_file_name, const string& weight_file_name, const string & flow_flie_name, const string & datacenter_file_name){
		links_import_from_file(weight_file_name);
		nodes_import_from_file(nodes_file_name,datacenter_file_name);
		flows_import_from_file(flow_flie_name);
	};

	NetStruture(){};

	~NetStruture(void);

	/// Getter and Setter
	double get_weight(int start_vertex, int end_vertex)const{
		return this->links.at(start_vertex).at(end_vertex)->GetWeight();
	}

	double get_flow(int start_vertex, int end_vertex)const{
		return this->s_d_flows.at(start_vertex).at(end_vertex);
	};

	Node get_node(int id)const{
		return this->nodes.at(id);
	}

	NetStruture(const NetStruture &NS);

	void close_node(int node_id );
	void open_node(int node_id );
	bool check_subject(PATHS paths);
	double compute_power();

	PATHS compute_all_shortest_path();

	void green_network();
	int Num_of_node() const { return num_of_node; }
	void Num_of_node(int val) { num_of_node = val; }

	map<int,Node> Nodes() const { return nodes; }
	void Nodes(map<int,Node> val) { nodes = val; }

	map<int,map<int,Link*>> Links() const { return links; }
	void Links(map<int,map<int,Link*>> val) { links = val; }

	map<int,map<int,double>> S_d_flows() const { return s_d_flows; }
	void S_d_flows(map<int,map<int,double>> val) { s_d_flows = val; }

protected:
	//members
	int num_of_node;
	S_D_FLOWS s_d_flows;
	NODES nodes;
	LINKS links;
	int num_of_link;
private:
	void clear(){
		this->links.clear();
		this->nodes.clear();
		this->s_d_flows.clear();
		this->num_of_node = 0;
	};
	void links_import_from_file(const std::string& input_file_name);
	void flows_import_from_file(const std::string& input_file_name);
	void nodes_import_from_file(const string & netlevel_file, const string & datacenter_file);
//	static bool less_occ_less_flow_chance_on_node(const Node& n1, const Node& n2);
	template <typename T>
	static bool less_occ_less_flow_chonce(const T& L1, const T& L2);
	void compute_node_occurrence( PATHS paths );
	void compute_link_occurrence( PATHS paths );
	bool is_connected();
	void close_link( Link &L );
	void open_link( Link  &L );


	int check_flow(double flow,vector<vector<int>>& s_d_path);
	vector<int> select_path(vector<vector<int>>& s_d_path);
	void arrange_flow(double f,vector<int>& a_path);
};

